﻿# based on Micsig's offical code written by Matlab.
# python verison,
# first created at Aug18,2023
# v1.1.20231228
#    * 修改了垂直档位部分
# by Fengxh@zz
#
'''
#usage:
import sys
#micsig_binRead_fft所在的相对路径
sys.path.append("..")
import micsig_bin_read as micsig;
 
#usage:
#打印频谱：plot_spectrum(micsig_bin_file, resample_ratio);
micsig.plot_spectrum(r'2308230111.bin', 100);
#打印波形：draw_scope_ch_wave(micsig_bin_file, resample_ratio, False);
micsig.draw_scope_ch_wave(r'2308230112.bin', 1000, False)
'''
import struct #for structual read
import numpy as np #for array
import matplotlib.pyplot as plt #for plot.
import pandas as pd
'''
STO1004 header. input...v.
00000000h: 11 04 18 20 01 00 00 00 60 07 0B 01 04 00 00 00 ; ... ....`.......
00000010h: 00 00 00 00 00 00 00 00 BB 02 00 00 00 00 00 00 ; ........?......
00000020h: D0 12 33 41 00 00 00 00 00 00 00 00 FE FF FF FF ; ?3A........?
00000030h: 00 00 00 00 00 00 00 00 00 00 24 40 00 00 00 00 ; ..........$@....
00000040h: 00 00 14 40 00 00 00 00 00 00 F0 3F 00 00 00 00 ; ...@......?....
00000050h: 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 ; ................
00000060h: 9A 99 99 99 99 99 B9 3F 0A 0F 9A 5D F7 D6 00 40 ; 殭櫃櫃?..歖髦.@
00000070h: 6E DB B6 6D DB E6 BB 40 80 1D 2C 04 01 00 00 00 ; n鄱m坻籃€.,.....
00000080h: 56 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; V...............
00000090h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000000a0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000000b0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000000c0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000000d0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000000e0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000000f0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
'''

class ScopeMicsig:
    #读入
    @staticmethod
    #return (x, wave, fs)
    def load_wavefile(filename_in_bin):
        file_name = filename_in_bin
        with open(file_name, 'rb') as f:
            f.seek(4); iWaveType = struct.unpack('i', f.read(4))[0] #offset.04 4
            f.seek(8); length = struct.unpack('i', f.read(4))[0] #offset0.8 4
            #y_scale = struct.unpack('i', f.read(4))[0] #?
            #x_scale = struct.unpack('i', f.read(4))[0] #?
            #f.seek(12, 1) 
            f.seek(0x34,0); probeMul = struct.unpack('<d', f.read(8))[0] #?probe type? 0:curr?
            f.seek(0x38,0); probeMul1 = struct.unpack('f', f.read(4))[0] #?probe x,
            #f.seek(12, 1)
            #fs = struct.unpack('d', f.read(8))[0]
            #f.seek(4, 1)
            '''
            if iWaveType == 2:
                f.seek(12, 1)
                fft_f_step = struct.unpack('f', f.read(4))[0]
                f.seek(4, 1)
            else:
                f.seek(4 * 5, 1)
            '''
            #num = struct.unpack('i', f.read(4))[0]
            f.seek(4, 1) #the last 1: 0:head;1:current;2:end.
            f.seek(0x44,0); timeScale = struct.unpack('d', f.read(8))[0];  #offset0x44 8
            f.seek(0x3c,0); vScale = struct.unpack('<d', f.read(8))[0];
            print(">>>>>>vScale:%lf, probeMul=%lf"  %(vScale, probeMul))
            vScale = vScale /probeMul / 50
            DataBits = struct.unpack('i', f.read(4))[0]
        
            f.seek(256)
            wave = np.frombuffer(f.read(length * 4), dtype=np.int32)
    
        fs = wave.size/(14*timeScale);
        x = np.arange(wave.size)
        x = x / fs
        #vScale = 1;
        wave = wave * vScale
        print(file_name,'total pt=', len(x), 'fs=', fs); 
        return (x, wave, fs)

    #读取micsig的csv类型
    def show_micsig_csv(file_path=r'D:\git\2025\20240930_10吨负载参照nxp的电流参数处理来\01.data\DG40T1228\2312280007.csv'):
        # 读取CSV文件
        #file_path =   #替换为你的CSV文件路径
        skip_rows = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
        df = pd.read_csv(file_path, skiprows=skip_rows)


        # 假设CSV文件有两列，列名分别为 'Column1' 和 'Column2'
        # 你可以根据实际情况替换列名
        x = df['Time']
        y = df['Value']
        return (x,y)

    @staticmethod
    def draw_scope_ch_wave(filename, re_sample_ratio, isWithFFT):
        percentStart = 50;
        percentStop = 100;
        #read
        (x,wave,fs) = scope_readwave_mini(filename);
    
        #sample
        x = x[::re_sample_ratio]; 
        y = wave[::re_sample_ratio];
        print('draw wave after sample: pt=', len(x));
        #截断
        lenPrev = len(x);
        startPt = int(percentStart*1.0*lenPrev/100);
        stopPt = int(percentStop*1.0*lenPrev/100);
        x = x[startPt:stopPt];
        y = y[startPt:stopPt];
        print('draw wave after slice: pt=', len(x), 'start pt=', startPt, ',stop pt=', stopPt);
    
        #plot it
        # 绘制波形图
        plt.figure(figsize=(8, 6))  # 设置画布大小，可根据需要调整
        plt.plot(x, y, color='blue', label='Waveform')  # 绘制波形曲线
        plt.xlabel('Time')  # 设置 x 轴标签
        plt.ylabel('Amplitude')  # 设置 y 轴标签
        plt.title('Waveform Plot' + '-' + filename)  # 设置图表标题
        plt.grid(True)  # 显示网格线
        plt.legend()  # 显示图例
        plt.show()  # 显示图形
    
    #file, ratio, start, stop
    @staticmethod
    def plot_spectrum(filename, re_sample_ratio):
        percentStart = 50;
        percentStop = 100;    
        #read
        (x,wave,fs) = scope_readwave_mini(filename);
     
    
        #sample
        print("pre x_max = %f, fs=%f;", x[-1], fs);
        x = x[::re_sample_ratio]; 
        y = wave[::re_sample_ratio];
        sampling_rate = fs/re_sample_ratio;
        signal = y;
        print("pos resampled(1:%d), x_max = %f, fs=%f", re_sample_ratio,  x[-1], sampling_rate);
        #截断
        lenPrev = len(x);
        startPt = int(percentStart*1.0*lenPrev/100);
        stopPt = int(percentStop*1.0*lenPrev/100);
        x = x[startPt:stopPt];
        y = y[startPt:stopPt];
        # 计算FFT
        fft_result = np.fft.fft(signal)
        # 移动FFT结果，使得负数频率位于两侧
        shifted_fft = np.fft.fftshift(fft_result)
        # 计算频率轴
        freq_axis = np.fft.fftshift(np.fft.fftfreq(len(signal), 1/sampling_rate))
        # 取FFT结果的绝对值
        spectrum = np.abs(shifted_fft)
        # 绘制频谱图
        plt.figure(figsize=(8, 4))
        plt.plot(freq_axis, spectrum)
        plt.title('Signal Spectrum')
        plt.xlabel('Frequency (Hz)')
        plt.ylabel('Amplitude')
        plt.grid(True)
        plt.show()
    '''
    %attachment code in Matlab version.
    %% 读取micsig mini示波器波形文件，包括wav文件和bin文件
    % file_name: 波形文件的文件名
    % x：返回波形数据x轴；
    % y：返回波形数据y轴；
    function [x,wave] = scope_readwave_mini(file_name)
    fid1 = fopen(file_name,'r');
    wave = [];
    x = [];
    if(fid1>0)
        fseek(fid1, 16, 'bof'); 
        iWaveType = fread(fid1, 1, 'int32');
        len = fread(fid1, 1, 'int32');
        y_scale = fread(fid1, 1, 'int32');
        x_scale = fread(fid1, 1, 'int32');
        fseek(fid1, 12, 'cof');
        probeType = fread(fid1, 1, 'int32');
        probeMul = fread(fid1, 1, 'float32');
        fseek(fid1, 12, 'cof');
        fs = fread(fid1, 1, 'float64');
        fseek(fid1, 4, 'cof');
        if(iWaveType == 2)
            fseek(fid1, 12, 'cof');
            fft_f_step = fread(fid1, 1, 'float32');
            fseek(fid1, 4, 'cof');
        else
            fseek(fid1, 4*5, 'cof');
        end
        num = fread(fid1, 1, 'int32');
        fseek(fid1, 4, 'cof');
        timeScale = fread(fid1, 1, 'float64');
        vScale = fread(fid1, 1, 'float64')*probeMul/50;
        DataBits = fread(fid1, 1, 'int32');
    
        fseek(fid1, 200, 'bof'); 
        if(DataBits == 32)
            [wave,cnt] = fread(fid1, len, 'int32');
        else
            [wave,cnt] = fread(fid1, len, 'int16');
        end
    else
        return;
    end
    x = 0:cnt-1;
    if(iWaveType == 2)
        x = x*fft_f_step;
    else
        x = x./fs;
    end
    wave = wave*vScale;
    '''